using System.ComponentModel;
using System.Runtime.Serialization;

using SharpGL.Enumerations;

namespace SharpGL.OpenGLAttributes
{
    /// <summary>
    /// This class has all the settings you can edit for pixel data.
    /// </summary>
    [TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))]
    [DataContract(/*IsReference = true, */Name = "PixelModeAttributes", Namespace = "SharpGL.SceneGraph")]
    public class PixelModeAttributes : OpenGLAttributes
    {
        #region Private Consts

        private static readonly AttributeMask attributeMask = AttributeMask.PixelMode;

        #endregion Private Consts

        #region Private Fields

        [DataMember()]
        private bool? mapColor;
        [DataMember()]
        private bool? mapStencil;
        [DataMember()]
        private int? indexShift;
        [DataMember()]
        private int? indexOffset;
        [DataMember()]
        private float? redScale;
        [DataMember()]
        private float? greenScale;
        [DataMember()]
        private float? blueScale;
        [DataMember()]
        private float? alphaScale;
        [DataMember()]
        private float? depthScale;
        [DataMember()]
        private float? redBias;
        [DataMember()]
        private float? greenBias;
        [DataMember()]
        private float? blueBias;
        [DataMember()]
        private float? alphaBias;
        [DataMember()]
        private float? depthBias;

        #endregion Private Fields

        #region Protected Methods

        protected override void OnDeserializing()
        {
            AttributeFlags = attributeMask;
        }

        #endregion Protected Methods

        #region Public Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="PixelModeAttributes"/> class.
        /// </summary>
        public PixelModeAttributes()
        {
            AttributeFlags = attributeMask;

            /*GL_RED_BIAS and GL_RED_SCALE settings

            GL_GREEN_BIAS and GL_GREEN_SCALE values

            GL_BLUE_BIAS and GL_BLUE_SCALE

            GL_ALPHA_BIAS and GL_ALPHA_SCALE

            GL_DEPTH_BIAS and GL_DEPTH_SCALE

            GL_INDEX_OFFSET and GL_INDEX_SHIFT values


            GL_ZOOM_X and GL_ZOOM_Y factors

            GL_READ_BUFFER setting*/
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Returns true if any attributes are set.
        /// </summary>
        /// <returns>
        /// True if any attributes are set
        /// </returns>
        public override bool AreAnyAttributesSet()
        {
            return
                mapColor.HasValue ||
                mapStencil.HasValue ||
                indexShift.HasValue ||
                indexOffset.HasValue ||
                redScale.HasValue ||
                greenScale.HasValue ||
                blueScale.HasValue ||
                alphaScale.HasValue ||
                depthScale.HasValue ||
                redBias.HasValue ||
                greenBias.HasValue ||
                blueBias.HasValue ||
                alphaBias.HasValue ||
                depthBias.HasValue;
        }

        /// <summary>
        /// Reset all attributes to unset state.
        /// </summary>
        public override void ResetAllAttributes()
        {
            mapColor = null;
            mapStencil = null;
            indexShift = null;
            indexOffset = null;
            redScale = null;
            greenScale = null;
            blueScale = null;
            alphaScale = null;
            depthScale = null;
            redBias = null;
            greenBias = null;
            blueBias = null;
            alphaBias = null;
            depthBias = null;
        }

        /// <summary>
        /// Sets the attributes.
        /// </summary>
        /// <param name="gl">The OpenGL instance.</param>
        public override void SetAttributes(OpenGL gl)
        {
            if (mapColor.HasValue) gl.PixelTransfer(PixelTransferParameterName.MapColor, mapColor.Value);
            if (mapStencil.HasValue) gl.PixelTransfer(PixelTransferParameterName.MapStencil, mapStencil.Value);
            if (indexShift.HasValue) gl.PixelTransfer(PixelTransferParameterName.IndexShift, indexShift.Value);
            if (indexOffset.HasValue) gl.PixelTransfer(PixelTransferParameterName.IndexOffset, indexOffset.Value);
            if (redScale.HasValue) gl.PixelTransfer(PixelTransferParameterName.RedScale, redScale.Value);
            if (greenScale.HasValue) gl.PixelTransfer(PixelTransferParameterName.GreenScale, greenScale.Value);
            if (blueScale.HasValue) gl.PixelTransfer(PixelTransferParameterName.BlueScale, blueScale.Value);
            if (alphaScale.HasValue) gl.PixelTransfer(PixelTransferParameterName.AlphaScale, alphaScale.Value);
            if (depthScale.HasValue) gl.PixelTransfer(PixelTransferParameterName.DepthScale, depthScale.Value);
            if (redBias.HasValue) gl.PixelTransfer(PixelTransferParameterName.RedBias, redBias.Value);
            if (greenBias.HasValue) gl.PixelTransfer(PixelTransferParameterName.GreenBias, greenBias.Value);
            if (blueBias.HasValue) gl.PixelTransfer(PixelTransferParameterName.BlueBias, blueBias.Value);
            if (alphaBias.HasValue) gl.PixelTransfer(PixelTransferParameterName.AlphaBias, alphaBias.Value);
            if (depthBias.HasValue) gl.PixelTransfer(PixelTransferParameterName.DepthBias, depthBias.Value);
        }

        #endregion Public Methods

        #region Public Properties

        /// <summary>
        /// Gets or sets the color of the map.
        /// </summary>
        /// <value>
        /// The color of the map.
        /// </value>
        [Description("Map color"), Category("Pixel mode attributes")]
        public bool? MapColor
        {
            get { return mapColor; }
            set
            {
                if (mapColor != value)
                {
                    mapColor = value;

                    NotifyPropertyChanged("MapColor");
                }
            }
        }

        /// <summary>
        /// Gets or sets the map stencil.
        /// </summary>
        /// <value>
        /// The map stencil.
        /// </value>
        [Description("Map stencil"), Category("Pixel mode attributes")]
        public bool? MapStencil
        {
            get { return mapStencil; }
            set
            {
                if (mapStencil != value)
                {
                    mapStencil = value;

                    NotifyPropertyChanged("MapStencil");
                }
            }
        }

        /// <summary>
        /// Gets or sets the index shift.
        /// </summary>
        /// <value>
        /// The index shift.
        /// </value>
        [Description("Index shift"), Category("Pixel mode attributes")]
        public int? IndexShift
        {
            get { return indexShift; }
            set
            {
                if (indexShift != value)
                {
                    indexShift = value;

                    NotifyPropertyChanged("IndexShift");
                }
            }
        }

        /// <summary>
        /// Gets or sets the index offset.
        /// </summary>
        /// <value>
        /// The index offset.
        /// </value>
        [Description("Index offset"), Category("Pixel mode attributes")]
        public int? IndexOffset
        {
            get { return indexOffset; }
            set
            {
                if (indexOffset != value)
                {
                    indexOffset = value;

                    NotifyPropertyChanged("IndexOffset");
                }
            }
        }

        /// <summary>
        /// Gets or sets the red scale.
        /// </summary>
        /// <value>
        /// The red scale.
        /// </value>
        [Description("Red scale"), Category("Pixel mode attributes")]
        public float? RedScale
        {
            get { return redScale; }
            set
            {
                if (redScale != value)
                {
                    redScale = value;

                    NotifyPropertyChanged("RedScale");
                }
            }
        }

        /// <summary>
        /// Gets or sets the green scale.
        /// </summary>
        /// <value>
        /// The green scale.
        /// </value>
        [Description("Green scale"), Category("Pixel mode attributes")]
        public float? GreenScale
        {
            get { return greenScale; }
            set
            {
                if (greenScale != value)
                {
                    greenScale = value;

                    NotifyPropertyChanged("GreenScale");
                }
            }
        }

        /// <summary>
        /// Gets or sets the blue scale.
        /// </summary>
        /// <value>
        /// The blue scale.
        /// </value>
        [Description("Blue scale"), Category("Pixel mode attributes")]
        public float? BlueScale
        {
            get { return blueScale; }
            set
            {
                if (blueScale != value)
                {
                    blueScale = value;

                    NotifyPropertyChanged("BlueScale");
                }
            }
        }

        /// <summary>
        /// Gets or sets the alpha scale.
        /// </summary>
        /// <value>
        /// The alpha scale.
        /// </value>
        [Description("Alpha scale"), Category("Pixel mode attributes")]
        public float? AlphaScale
        {
            get { return alphaScale; }
            set
            {
                if (alphaScale != value)
                {
                    alphaScale = value;

                    NotifyPropertyChanged("AlphaScale");
                }
            }
        }

        /// <summary>
        /// Gets or sets the depth scale.
        /// </summary>
        /// <value>
        /// The depth scale.
        /// </value>
        [Description("Depth scale"), Category("Pixel mode attributes")]
        public float? DepthScale
        {
            get { return depthScale; }
            set
            {
                if (depthScale != value)
                {
                    depthScale = value;

                    NotifyPropertyChanged("DepthScale");
                }
            }
        }

        /// <summary>
        /// Gets or sets the red bias.
        /// </summary>
        /// <value>
        /// The red bias.
        /// </value>
        [Description("Red bias"), Category("Pixel mode attributes")]
        public float? RedBias
        {
            get { return redBias; }
            set
            {
                if (redBias != value)
                {
                    redBias = value;

                    NotifyPropertyChanged("RedBias");
                }
            }
        }

        /// <summary>
        /// Gets or sets the green bias.
        /// </summary>
        /// <value>
        /// The green bias.
        /// </value>
        [Description("Green bias"), Category("Pixel mode attributes")]
        public float? GreenBias
        {
            get { return greenBias; }
            set
            {
                if (greenBias != value)
                {
                    greenBias = value;

                    NotifyPropertyChanged("GreenBias");
                }
            }
        }

        /// <summary>
        /// Gets or sets the blue bias.
        /// </summary>
        /// <value>
        /// The blue bias.
        /// </value>
        [Description("Blue bias"), Category("Pixel mode attributes")]
        public float? BlueBias
        {
            get { return blueBias; }
            set
            {
                if (blueBias != value)
                {
                    blueBias = value;

                    NotifyPropertyChanged("BlueBias");
                }
            }
        }

        /// <summary>
        /// Gets or sets the alpha bias.
        /// </summary>
        /// <value>
        /// The alpha bias.
        /// </value>
        [Description("Alpha bias"), Category("Pixel mode attributes")]
        public float? AlphaBias
        {
            get { return alphaBias; }
            set
            {
                if (alphaBias != value)
                {
                    alphaBias = value;

                    NotifyPropertyChanged("AlphaBias");
                }
            }
        }

        /// <summary>
        /// Gets or sets the depth bias.
        /// </summary>
        /// <value>
        /// The depth bias.
        /// </value>
        [Description("Depth bias"), Category("Pixel mode attributes")]
        public float? DepthBias
        {
            get { return depthBias; }
            set
            {
                if (depthBias != value)
                {
                    depthBias = value;

                    NotifyPropertyChanged("DepthBias");
                }
            }
        }

        #endregion Public Properties
    }
}
